﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace ShootThemUp.Sources.GameElements
{
    /// <summary>
    /// Sprite is a class used to draw texture2D.
    /// </summary>
    public class Sprite
    {
        #region Fields

        private Vector2 position;
        private Texture2D texture;
        private Rectangle? hitbox = null;
        private Rectangle? sourceRectangle = null;
        private Color color = Color.White;
        private float rotation = 0; //RAD
        private Vector2 origin = Vector2.Zero;
        private Vector2 scale = Vector2.One;
        private SpriteEffects effect = SpriteEffects.None;
        private float layerDepth = 0;
        private Vector2 hitboxOrigin = new Vector2(0,0);

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the source rectangle, ie the rectangle zone to display in the spritesheet.
        /// </summary>
        /// <value>
        /// Returns the source rectangle.
        /// </value>
        public Rectangle? SourceRectangle
        {
            get { return this.sourceRectangle; }
            set { this.sourceRectangle = value; }
        }

        /// <summary>
        /// Gets or sets the position of the sprite.
        /// </summary>
        /// <value>
        /// Returns the position.
        /// </value>
        public Vector2 Position
        {
            get { return this.position; }
            set { this.position = value; }
        }

        /// <summary>
        /// Gets the texture of the sprite.
        /// </summary>
        public Texture2D Texture
        {
            get { return texture; }
        }

        

        public Vector2 HitboxOrigin
        {
            get { return hitboxOrigin; }
            set { hitboxOrigin = value; }
        }
        

        /// <summary>
        /// Gets or sets the hitbox of the sprite.
        /// </summary>
        /// <value>
        /// The hitbox.
        /// </value>
        public Rectangle? Hitbox
        {
            get
            {
                Rectangle hitbox;

                if (this.hitbox == null)
                {
                    if (this.sourceRectangle == null)
                    {
                        hitbox = new Rectangle((int)this.Position.X - (int)this.Origin.X, (int)this.Position.Y - (int)this.Origin.Y, this.Texture.Width, this.Texture.Height);
                    }
                    else
                    {
                        hitbox = new Rectangle((int)this.Position.X - (int)this.Origin.X, (int)this.Position.Y - (int)this.Origin.Y, this.sourceRectangle.Value.Width, this.sourceRectangle.Value.Height);
                    }
                }
                else
                {
                    
                    hitbox = new Rectangle(((int)this.Position.X + (int)this.hitboxOrigin.X), (int)this.Position.Y + (int)this.hitboxOrigin.Y, this.hitbox.Value.Width, this.hitbox.Value.Height);
                }

                return hitbox;
            }
            set { this.hitbox = value; }
        }

        /// <summary>
        /// Gets or sets the filter color of the sprite.
        /// </summary>
        /// <value>
        /// Returns the color.
        /// </value>
        public Color Color
        {
            get { return this.color; }
            set { this.color = value; }
        }

        /// <summary>
        /// Gets or sets the rotation angle of the sprite, in radians.
        /// </summary>
        /// <value>
        /// The rotation angle of the sprite, in radians.
        /// </value>
        public float Rotation
        {
            get { return this.rotation; }
            set { this.rotation = value; }
        }

        /// <summary>
        /// Gets or sets the origin of the rotation.
        /// </summary>
        /// <value>
        /// The origin of the rotation.
        /// </value>
        public Vector2 Origin
        {
            get { return this.origin; }
            set { this.origin = value; }
        }

        /// <summary>
        /// Gets or sets the scale of the sprite.
        /// </summary>
        /// <value>
        /// Returns the scale of the sprite.
        /// </value>
        public Vector2 Scale
        {
            get { return this.scale; }
            set { this.scale = value; }
        }

        /// <summary>
        /// Gets or sets the effect of the sprite (flips).
        /// </summary>
        /// <value>
        /// The sprite effect.
        /// </value>
        public SpriteEffects Effect
        {
            get { return this.effect; }
            set { this.effect = value; }
        }

        /// <summary>
        /// Gets or sets the layer depth, ie the display priority of the sprite.
        /// </summary>
        /// <value>
        /// The layer depth.
        /// </value>
        public float LayerDepth
        {
            get { return this.layerDepth; }
            set { this.layerDepth = value; }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        public Sprite() 
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        /// <param name="position">The position of the sprite.</param>
        public Sprite(Vector2 position)
        {
            this.position = position;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        /// <param name="position">The position of the sprite.</param>
        /// <param name="sourceRectangle">The source rectangle.</param>
        public Sprite(Vector2 position, Rectangle? sourceRectangle)
            : this(position, sourceRectangle, null)
        {
        }

        public Sprite(Vector2 position, Rectangle? sourceRectangle, Rectangle? hitbox)
        {
            this.Position = position;
            this.SourceRectangle = sourceRectangle;
            this.hitbox = hitbox;
            if (this.hitbox != null)
            {
                this.hitboxOrigin = new Vector2(hitbox.Value.X, hitbox.Value.Y);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Loads the Texture2D in the game.
        /// </summary>
        /// <param name="content">The content manager.</param>
        /// <param name="assetName">Name of the asset to load.</param>
        public virtual void LoadContent(ContentManager content, string assetName)
        {
            texture = content.Load<Texture2D>(assetName);
        }

        /// <summary>
        /// Draws this sprite in the specified sprite batch.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch.</param>
        public virtual void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, position, sourceRectangle, color, rotation, origin, scale, effect, layerDepth);
        }

        #endregion
    }
}
